package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.model.user.UserPaidAlbum;
import com.atguigu.tingshu.model.user.UserPaidTrack;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.AlbumTrackListVo;
import com.atguigu.tingshu.vo.album.TrackInfoVo;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.album.TrackMediaInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;
	@Autowired
	private AlbumInfoMapper albumInfoMapper;
	@Autowired
	private TrackStatMapper trackStatsMapper;
	@Autowired
	private AlbumStatMapper albumStatMapper;
	@Autowired
	private VodService vodService;
	@Autowired
	private UserInfoFeignClient userInfoFeignClient;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(TrackInfoVo trackInfoVo, long userId) {
		// 封装TrackInfo对象并添加进数据库表中
		TrackInfo trackInfo = new TrackInfo();
		BeanUtils.copyProperties(trackInfoVo, trackInfo);
		//添加vo中没有的内容
		trackInfo.setUserId(userId);
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		trackInfo.setOrderNum(albumInfo.getIncludeTrackCount()+1);
		//添加流媒体内容
		TrackMediaInfoVo mediaInfoVo=vodService.getMediaInfo(trackInfoVo.getMediaFileId());
		if (mediaInfoVo!=null){
			trackInfo.setMediaDuration(BigDecimal.valueOf(mediaInfoVo.getDuration()));
			trackInfo.setMediaSize(mediaInfoVo.getSize());
			trackInfo.setMediaType(mediaInfoVo.getType());
			trackInfo.setMediaUrl(mediaInfoVo.getMediaUrl());
		}
		trackInfoMapper.insert(trackInfo);
		//修改专辑中声音数量
		albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()+1);
		//专辑声音数量+1
		albumInfoMapper.updateById(albumInfo);
		//添加声音统计
		saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
		saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
		saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
		saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);
	}

	@Override
	public void findUserTrackPage(Page<TrackListVo> page, TrackInfoQuery trackInfoQuery) {
		page = trackInfoMapper.findUserTrackPage(page,trackInfoQuery);
	}

	@Override
	public void updateTrackInfo(TrackInfoVo trackInfoVo, Long trackId) {
		//获取原数据
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		String mediaFileId = trackInfo.getMediaFileId();
		//拷贝数据到新对象
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		if (!mediaFileId.equals(trackInfoVo.getMediaFileId())){//说明声音被修改
			vodService.deleteMedia(mediaFileId);
			//修改新的流媒体信息
			TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
			trackInfo.setMediaDuration(BigDecimal.valueOf(mediaInfo.getDuration()));
			trackInfo.setMediaSize(mediaInfo.getSize());
			trackInfo.setMediaType(mediaInfo.getType());
			trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
		}
		trackInfoMapper.updateById(trackInfo);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfo(Long trackId) {
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		trackInfoMapper.deleteById(trackInfo);
		trackStatsMapper.delete(new LambdaQueryWrapper<TrackStat>()
				.eq(TrackStat::getTrackId,trackId));
		albumInfoMapper.updateAlbumInfo(trackInfo.getAlbumId());
		vodService.deleteMedia(trackInfo.getMediaFileId());
	}

	@Override
	public void findAlbumTrackPage(Page<AlbumTrackListVo> page, Long albumId, Long userId) {
		//根据专辑id获取到声音信息
		page = trackInfoMapper.findAlbumTrackPage(page,albumId);
		//获取专辑付费类型
		AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
		if (albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_FREE)){//专辑免费
			return;
		}
		//专辑vip免费或付费
		if (userId == null){//未登录
			//获取免费试听集数
			Integer tracksForFreeNum = albumInfo.getTracksForFree();
			page.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFreeNum).forEach(
					albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true)
			);
			return;
		}else {//已登录
			//远程获取用户信息
			Result<UserInfo> userInfoResult = userInfoFeignClient.getUserInfo(userId);
			Assert.notNull(userInfoResult, "user远程调用失败");
			UserInfo userInfo = userInfoResult.getData();
			Assert.notNull(userInfo, "用户为空");
			if (userInfo.getIsVip()==1 && userInfo.getVipExpireTime().after(new Date())){//用户是vip
				if (albumInfo.getPayType().equals(SystemConstant.ALBUM_PAY_TYPE_VIPFREE)){//专辑vip免费
					return;
				}
			}
			//用户不是vip或专辑不是vip免费
			//取得该专辑所有声音id
			List<Long> allTrackIdList = page.getRecords().stream().map(AlbumTrackListVo::getTrackId).collect(Collectors.toList());
			//远程调用获取用户购买的该专辑的声音信息与免费试听声音id
			Result<List<Long>> paidTrackIdResult = userInfoFeignClient.getPaidTrack(albumId,allTrackIdList);
			Assert.notNull(paidTrackIdResult, "user远程调用失败");
			List<Long> paidTrackIdList = paidTrackIdResult.getData();
			if (CollectionUtils.isEmpty(paidTrackIdList)){//未购买任何声音
				Integer tracksForFreeNum = albumInfo.getTracksForFree();
				page.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFreeNum).forEach(
						albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true)
				);
			}else {
				//获取用户购买声音id的map
				Map<Long, Integer> map = paidTrackIdList.stream().collect(Collectors.toMap(paidTrackId -> paidTrackId, paidTrackId -> 1));
				Integer tracksForFreeNum = albumInfo.getTracksForFree();
				if (!CollectionUtils.isEmpty(map)){
					page.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFreeNum &&
							!map.containsKey(albumTrackListVo.getTrackId())).forEach(
							albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true)
					);
				}else {
					page.getRecords().stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > tracksForFreeNum).forEach(
							albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true)
					);
				}

			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void updateStat(Long trackId, Long albumId, String statType, Integer count) {
		//修改声音统计信息
		trackStatsMapper.increaseStatNum(trackId, statType, count);
		//修改专辑统计信息
		String albumStatType;
		if (statType.equals(SystemConstant.TRACK_STAT_PLAY)){
			albumStatType = SystemConstant.ALBUM_STAT_PLAY;
			albumStatMapper.increaseStatNum(albumId, albumStatType, count);
		}
	}

	@Override
	public List<Map<String, Object>> findUserTrackPaidList(Long trackId, Long userId) {
		//初始化返回对象
		List<Map<String, Object>> list = new ArrayList<>();
		//获取当前声音信息
		TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
		//获取声音对应专辑信息
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		//远程调用获取用户购买的该专辑的声音id信息
		Result<List<Long>> paidTrackResult = userInfoFeignClient.getPaidTrack(albumInfo.getId(), Collections.singletonList(trackId));
		Assert.notNull(paidTrackResult, "user远程调用失败");
		List<Long> paidTrackList = paidTrackResult.getData();
		//获取所有可购买的专辑声音信息
		LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, albumInfo.getId())
				.ge(TrackInfo::getOrderNum, trackInfo.getOrderNum());
		if (!CollectionUtils.isEmpty(paidTrackList)){
			wrapper.notIn(TrackInfo::getId, paidTrackList);
		}
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(wrapper);
		Map<String, Object> map = new HashMap<>();
		//购买本集
		map.put("name","本集");
		map.put("price",albumInfo.getPrice());
		map.put("trackCount",0);
		list.add(map);
		int size = trackInfoList.size();
		for (int i = 1; i <= size/10 && i <=3; i++) {
			//购买n*10集
			map = new HashMap<>();
			map.put("name","后"+i*10+"集");
			map.put("price",albumInfo.getPrice().multiply(new BigDecimal(i*10+"")));
			map.put("trackCount",i*10);
			list.add(map);
		}
		if ((size > 1 && size % 10 != 0) || size > 30){
			//购买剩下的所有集
			map = new HashMap<>();
			map.put("name","后"+size+"集");
			map.put("price",albumInfo.getPrice().multiply(new BigDecimal(String.valueOf(size))));
			map.put("trackCount",size);
			list.add(map);
		}
		return list;
	}

	@Override
	public List<TrackInfo> getTrackListById(Long trackId, Integer trackCount, Long userId) {
		//获取当前声音信息
		TrackInfo trackInfo = getById(trackId);
		//获取声音对应专辑信息
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());
		Result<List<Long>> paidTrackResult = userInfoFeignClient.getPaidTrack(albumInfo.getId(), Collections.singletonList(trackId));
		Assert.notNull(paidTrackResult, "user远程调用失败");
		//获取用户购买的该专辑的声音id列表
		List<Long> paidTrackList = paidTrackResult.getData();
		LambdaQueryWrapper<TrackInfo> wrapper = new LambdaQueryWrapper<TrackInfo>()
				.eq(TrackInfo::getAlbumId, albumInfo.getId())
				.ge(TrackInfo::getOrderNum, trackInfo.getOrderNum());
		if (!CollectionUtils.isEmpty(paidTrackList)){
			wrapper.notIn(TrackInfo::getId, paidTrackList);
		}
		if (trackCount == 0){
			wrapper.last("limit 1");
		}else {
			wrapper.last("limit "+trackCount);
		}
		List<TrackInfo> trackInfoList = trackInfoMapper.selectList(wrapper);
		return trackInfoList;
	}

	/**
	 * 添加声音统计信息
	 * @param trackId
	 * @param statType
	 */
	private void saveTrackStat(Long trackId, String statType) {
		TrackStat trackStat = new TrackStat();
		trackStat.setTrackId(trackId);
		trackStat.setStatType(statType);
		trackStat.setStatNum(new Random().nextInt(100));
		trackStatsMapper.insert(trackStat);
	}
}
